﻿#include <iostream>
#include <learn/gl/gl_callback.h>

using namespace xi;
using namespace xi::gl;
using namespace xi::geom;

namespace
{

enum class Action3d
{
    None,
    Rotate,
    Scale
};

float angleRate = 0.25f;
float scaleRate = 2.0f;
Action3d mouseAction = Action3d::None;

} // namespace

void xi::gl::transform(GLFWwindow *window)
{
    glMatrixMode(GL_PROJECTION);

    int width, height;
    glfwGetWindowSize(window, &width, &height);

    // 注意需要转置（glm 不需要转置）
    globalCamera.resize(width, height);
    glLoadMatrixf(globalCamera.projection().transposed().data);

    glMatrixMode(GL_MODELVIEW);

    glLoadMatrixf(globalCamera.view().transposed().data);
}

void xi::gl::GLFWWindowResize(GLFWwindow *window, int width, int height)
{
    glViewport(0, 0, width, height);
}

void xi::gl::GLFWMouseButtonCallback(GLFWwindow *window, int button, int action, int mode)
{
    if (button == GLFW_MOUSE_BUTTON_MIDDLE)
    {
        if (mouseAction == Action3d::None && action == GLFW_PRESS)
            mouseAction = Action3d::Rotate;

        if (mouseAction == Action3d::Rotate && action == GLFW_RELEASE)
            mouseAction = Action3d::None;
    }
}

void xi::gl::GLFWCursorPosCallback(GLFWwindow *window, double xpos, double ypos)
{
    static float px, py;

    if (mouseAction == Action3d::Rotate)
    {
        globalCamera.rotate((px - xpos) * angleRate, (py - ypos) * angleRate);
    }

    px = xpos;
    py = ypos;
}

void xi::gl::GLFWScrollCallback(GLFWwindow *window, double xoffset, double yoffset)
{
    if (mouseAction == Action3d::None)
    {
        mouseAction = Action3d::Scale;

        double px, py;
        glfwGetCursorPos(window, &px, &py);

        globalCamera.translate(Vec2f{(float)px, (float)py}, scaleRate * -yoffset);

        mouseAction = Action3d::None;
    }
}

void xi::gl::GLFWKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
    if (action == GLFW_PRESS)
    {
        if (key == GLFW_KEY_ESCAPE)
            glfwSetWindowShouldClose(window, GLFW_TRUE);
        if (key == GLFW_KEY_UP)
            globalCamera.rotate_front(Vec3f{0.0f, 0.0f, 1.0f} * angleRate);
        if (key == GLFW_KEY_DOWN)
            globalCamera.rotate_front(Vec3f{0.0f, 0.0f, -1.0f} * angleRate);
        if (key == GLFW_KEY_0)
            globalCamera.set_center(Vec3f{0.0f, 0.0f, 0.0f});
        if (key == GLFW_KEY_1)
            globalCamera.upright_view();
        if (key == GLFW_KEY_3)
            globalCamera.right_view();
        if (key == GLFW_KEY_7)
            globalCamera.top_view();
        if (key == GLFW_KEY_9)
            globalCamera.bottom_view();
    }
}

void xi::gl::GLFWDropCallback(GLFWwindow *window, int path_count, const char **paths)
{
}